#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include "buildsettings.h"
#include "perfecthashtable.h"
#include "errorcodes.h"

int perfecthashtable_set(PerfectHashTable *pht, char *key, void *value);
void *perfecthashtable_get(PerfectHashTable *pht, char *key);

/*! Create a perfect hash table
  /param size Size of the array in the parent hash table
  /return The new HashTable object. NOTE: Not a pointer
*/
PerfectHashTable new_PerfectHashTable(int size)
{
	PerfectHashTable pht;
	pht.ht = new(HashTable, size);
	pht.Get = &perfecthashtable_get;
	pht.Set = &perfecthashtable_set;
	return pht;
}

/*! Destroy a perfect hash table
  /param ht A pointer to the hash table to deconstruct. Passing a regular hash table will create a memory error.
*/
void destroy_PerfectHashTable(PerfectHashTable *pht)
{
	int i;
	HashTablePair *pair;
	for (i=0; i<pht->ht.Size; i++)
	{
		pair = pht->ht.Pairs[i];
		if (pair != 0x0)
		{
			destroy_HashTable(pair->Value);
			free(pair->Value);
			pair->Value = 0x0;
			free(pair);
			pht->ht.Pairs[i] = 0x0;
		}
	}
}

/*!
  Set a value in a perfect hash table.
  /param pht Perfect hash table on which to perform operations
  /param key A unique null-terminated string key
  /param value A pointer to a dynamically-allocated memory block
  /return An error code based on the project error codes. Defined in errorcodes.h
*/
int perfecthashtable_set(PerfectHashTable *pht, char *key, void *value)
{
	HashTable *lowTable = pht->ht.Get(&(pht->ht), key);
	if (lowTable == 0x0)
	{
		HashTable ht = new(HashTable, 20);
		lowTable = (HashTable*)malloc(sizeof(HashTable));
		memcpy(lowTable, &ht, sizeof(HashTable));
		lowTable->Set(lowTable, key, value);
		pht->ht.Set(&(pht->ht), key, lowTable);
		return EC_SUCCESS;
	}
	return lowTable->Set(lowTable, key, value);
}
/*!
  Get a value from a perfect hash table.
  /param pht Perfect hash table on which to perform operations
  /param key A unique null-terminated string key
  /return A pointer to the value, if successful, null otherwise
*/
void *perfecthashtable_get(PerfectHashTable *pht, char *key)
{
	HashTable *lowTable = pht->ht.Get(&(pht->ht), key);
	if (lowTable == 0x0)
		return 0x0;

	return lowTable->Get(lowTable, key);
}
